//
//  Codec.h
//  sad
//
//  Created by Christopher Kemsley on 2/3/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#ifndef sad_Codec_h
#define sad_Codec_h



#include "IAAny.hpp"
#include <typeinfo>
#include <string>
#include <map>
#include <vector>
#include <iostream>

#include "Log.hpp"


NamespaceBegin




struct	Codec
{
	
	template <typename ModelType,typename ViewType>
	static std::string const	typeHash	()
		{
		std::string	name	( typeid(ModelType).name() ) ;
		name += "..." ;
		name +=	typeid(ViewType).name() ;
		return name ;
		}
	static std::string const	typeHash	( std::type_info const& modelType , std::type_info const& viewType )
		{
		std::string	name	( modelType.name() ) ;
		return name + "..." + viewType.name() ;
		}
	
	
	
	template <typename ModelType,typename ViewType>
	static Codec*	codec	()
		{
		std::string	name	=	typeHash<ModelType,ViewType> () ;
		Log::states() << "Codec...\n	Searching for " << name ;
		std::map<std::string,Codec*>::iterator it = codecs() . find ( name ) ;
		if ( it == codecs().end() )
			return 0 ;
		return (*it) . second ;
		}
	
	static Codec*	codec	( std::type_info const& modelType , std::type_info const& viewType )
		{
		std::string	name	=	typeHash(modelType,viewType) ;
		Log::states() << "Codec...\n	Searching for " << name ;
		std::map<std::string,Codec*>::iterator it = codecs() . find ( name ) ;
		if ( it == codecs().end() )
			return 0 ;
		return (*it) . second ;
		}
	
	
	
	
	
	template <typename ViewType,typename ModelType>
	static bool		decode		( ViewType & view , ModelType & model )
		{
		Any const		anyView		=	&view ;
		Any const		anyModel	=	&model ;
		return decodeAny ( anyView , anyModel ) ;
		}
	
	template <typename ModelType>
	static bool		decode		( Any const & anyView , ModelType & model )
		{
		Any const		anyModel	=	&model ;
		return decodeAny ( anyView , anyModel ) ;
		}
	template <typename ViewType>
	static bool		decode		( ViewType & view , Any const & anyModel )
		{
		Any const		anyView		=	&view ;
		return decodeAny ( anyView , anyModel ) ;
		}
	
	static bool		decodeAny	( Any const & anyView , Any const & anyModel )
		{
		Codec*	decoder		=	codec(anyModel.type(),anyView.type()) ;
		
		if ( decoder != 0 )
			return decoder -> runDecode ( anyView , anyModel ) ;
		
		return false ;
		}
	
	
	
	
	// for subclasses
	virtual bool	runDecode	( Any const & view , Any const & model ) = 0 ;
	
protected:
	Codec ( std::string const& name )
		{
		codecs() [name] = this ;
		Log::states() << "Codec...\n	Registering " << name ;
		}
	
private:
	static std::map<std::string,Codec*>&	codecs()
		{
		static std::map<std::string,Codec*> m ;
		return m ;
		}
	
} ;







template <typename ModelType,typename ViewType>
struct	aCodec : public Codec
{
	
protected:
	aCodec ()
	:	Codec	( Codec::typeHash<ModelType const,ViewType const>() )
		{ }
	
} ;













NamespaceEnd

#endif
